using System.Diagnostics;

namespace FluentParser.Expressions.Rules.Composition
{
    /// <summary>
    /// Tries to parse using the first symbol and fallback to the
    /// second one in case of failure.
    /// </summary>
    /// <typeparam name="TSource">Type of the source expressions</typeparam>
    /// <example><code>
    /// var word = ParseString.Regex("[A-Za-z]+");
    /// var number = ParseString.Exact("[0-9]+");
    /// var choice = word | number;
    /// 
    /// choice.Parse("SomeText")            --> "SomeText"
    /// choice.Parse("123456789")           --> "123456789" (fallback)
    /// choice.Parse("_TextWithUnderscore") --> failure
    /// </code></example>
    [DebuggerDisplay("[ChoiceExpressionRule {Left.GetType().Name} Or {Right.GetType().Name}]")]
    public class ChoiceExpressionRule<TSource> : Expr<TSource> 
    {
        public Expr<TSource> Left { get; private set; }
        public Expr<TSource> Right { get; private set; }

        public ChoiceExpressionRule(Expr<TSource> left, Expr<TSource> right)
        {
            Left = left;
            Right = right;
            TypeOperation = OperationType.Choice;
        }

        public override ParsingResult<TSource> Parse(GrammarContext context, int index)
        {
            return Left.Parse(context, index) ?? Right.Parse(context, index);
        }

        public override void ParseNode(GrammarContext context, ParsingNodeResult node)
        {
            ParsingNodeResult leftNode = node.AddChild(Left, context);
            if (leftNode.IsSuccess)
            {
                node.IsSuccess = true;
                node.Value = leftNode.Value;
            }
            else
            {
                ParsingNodeResult rightNode = node.AddChild(Right, context);
                node.IsSuccess = rightNode.IsSuccess;
                node.Value = rightNode.Value;
            }
        }
    }
}